#!/usr/bin/python
import cv2
import time
import sys
import threading
import requests
import base64,glob
import json,os
import numpy as np
sys.path.insert(0, "..")
from opcua import Client
from opcua import ua

isCameraLinked = False
flag =False
Img = 0
count = 0

# opencv读取出来的图片相当于numpy数组
def cv2_to_base64(image):
    image1 = cv2.imencode('.jpg', image)[1]
    image_code = str(base64.b64encode(image1))[2:-1]
    return image_code

def base64_to_cv2(image_code):
    #解码
    img_data=base64.b64decode(image_code)
    #转为numpy
    img_array=np.fromstring(img_data,np.uint8)
    #转成opencv可用格式
    img=cv2.imdecode(img_array,cv2.COLOR_RGB2BGR)
    return img

'''
与服务器建立连接
若检测到flag为Ture，则代表空框
将端口值置设为True
'''
def establishMyClient(url,UserName,password):
    client = Client(url)
    client.set_user(username=UserName)
    client.set_password(password)
    global flag,flag_lock
    try:

        res = client.connect()
        root = client.get_root_node()

        myvar = root.get_child(["0:Objects", "3:ServerInterfaces", "4:Server interface_1","4:Bool","4:[0]"])
        # myvar = root.get_child(["0:Objects", "3:myobj","3:myvar"])
        while True:
            # start = time.time()
            if flag==True:
                myvar.set_value(True)
                flag_lock.acquire()
                flag=False
                flag_lock.release()
            time.sleep(0.1)
            # end = time.time()
            # print("连接服务器线程耗时：",end-start)


    finally:
        client.disconnect()


'''
空框检测
空框保持一段时间返回True
否则返回False
'''
def overlapDetection(rate,level_flag):
    global count,count_lock
    global flag,flag_lock
    if level_flag==0:#调试模式
        url = "http://192.168.0.202:8000/photo"
        while True:#
            if isCameraLinked == True:
                start = time.time()
                img = Img
                # cv2.imwrite(r'D:\vanderlandeProjectImg\dailytest\826\img' + str(time.time()) + ".jpg", img[:, :, [2, 1, 0]])
                # blurred = cv2.GaussianBlur(img, (3, 3), 0)  # 高斯模糊降噪
                gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 灰度图
                edge_output = cv2.Canny(gray, 50, 200)  # 不求梯度也可以
                contours, hierarchy = cv2.findContours(edge_output, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  # 轮廓发现
                areaAll = 0

                for i in contours:
                    # 最小矩形包围框
                    ret = cv2.minAreaRect(i)
                    # 得出矩形框的四个顶点
                    pts = cv2.boxPoints(ret)
                    pts = np.int0(pts)
                    cv2.drawContours(img, i, -1, (0, 255, 0), 2)
                    # 得出矩形框面积
                    area = cv2.contourArea(pts)
                    areaAll += area
                if areaAll / (edge_output.shape[0] * edge_output.shape[1]) > rate:#检测为非空框时
                    count_lock.acquire()
                    count = 0
                    count_lock.release()
                else:#检测为空框时
                    count_lock.acquire()
                    count +=1
                    count_lock.release()
                # print(areaAll)
                # 如果面积大于阈值，则认为是物体
                if count >= 5:
                    # cv2.imwrite(r'D:\vanderlandeProjectImg\dailytest\826\img' + str(time.time()) + "empty.jpg", img[:, :, [2, 1, 0]])
                    print("空框,count = ",count)
                    s=time.time()
                    name = str(time.time()) + "empty.jpg"
                    image_code = cv2_to_base64(img)
                    img = []
                    img.append(image_code)
                    # 拼接参数,上传到服务器
                    try:
                        files = {'file': img, 'name': name}
                        fff = json.dumps(files, ensure_ascii=False)
                        e=time.time()
                        print(e-s)
                        # 发送post请求到服务器端json.dumps(files, ensure_ascii=False)
                        # r = requests.post(url, json=json.dumps(files, ensure_ascii=False))
                        r = requests.post(url, json=fff)
                    except BaseException as e:
                        print(e)
                    flag_lock.acquire()
                    flag = True
                    flag_lock.release()
                elif count == 0:
                    # cv2.imwrite(r'D:\vanderlandeProjectImg\dailytest\826\img' + str(time.time()) + "notempty.jpg", img[:, :, [2, 1, 0]])
                    print("非空框,count = ",count)
                    name = str(time.time()) + "hasthing.jpg"
                    image_code = cv2_to_base64(img)
                    img = []
                    img.append(image_code)
                    # 拼接参数
                    try:
                        files = {'file': img, 'name': name}
                        fff = json.dumps(files, ensure_ascii=False)
                        # 发送post请求到服务器端json.dumps(files, ensure_ascii=False)
                        # r = requests.post(url, json=json.dumps(files, ensure_ascii=False))
                        r = requests.post(url, json=fff)
                    except BaseException as e:
                        print(e)
                    flag_lock.acquire()
                    flag = False
                    flag_lock.release()
                else:
                    # cv2.imwrite(r'D:\vanderlandeProjectImg\dailytest\826\img' + str(time.time()) + "emptyy.jpg", img[:, :, [2, 1, 0]])
                    print("空框但持续时间不够,count = ",count)
                    name = str(time.time()) + "undetermined.jpg"
                    image_code = cv2_to_base64(img)
                    img = []
                    img.append(image_code)
                    try:
                        # 拼接参数
                        files = {'file': img, 'name': name}
                        fff = json.dumps(files, ensure_ascii=False)
                        # 发送post请求到服务器端json.dumps(files, ensure_ascii=False)
                        # r = requests.post(url, json=json.dumps(files, ensure_ascii=False))
                        r = requests.post(url, json=fff)
                    except BaseException as e:
                        print(e)
                    flag_lock.acquire()
                    flag = False
                    flag_lock.release()
                time.sleep(0.1)
                end = time.time()
                # print("算法耗时为：", end - start)
            time.sleep(0.1)
    if level_flag==1:
        while True:
            if isCameraLinked == True:
                img = Img
                # blurred = cv2.GaussianBlur(img, (3, 3), 0)  # 高斯模糊降噪
                gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)  # 灰度图
                edge_output = cv2.Canny(gray, 50, 200)  # 不求梯度也可以
                contours, hierarchy = cv2.findContours(edge_output, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)  # 轮廓发现
                # c = sorted(contours, key=cv2.contourArea, reverse=True)
                # 构造逼近多边形
                areaAll = 0

                for i in contours:
                    # 最小矩形包围框
                    ret = cv2.minAreaRect(i)
                    #得出矩形框的四个顶点
                    pts = cv2.boxPoints(ret)
                    pts = np.int0(pts)
                    #得出矩形框面积
                    area = cv2.contourArea(pts)
                    areaAll += area
                if areaAll / (edge_output.shape[0] * edge_output.shape[1]) > rate:#检测为非空框时
                    count_lock.acquire()
                    count = 0
                    count_lock.release()
                else:#检测为空框时
                    count_lock.acquire()
                    count +=1
                    count_lock.release()
                # 如果面积大于阈值，则认为是物体
                if count >= 5:
                    flag_lock.acquire()
                    flag = True
                    flag_lock.release()
                elif count == 0:
                    flag_lock.acquire()
                    flag = False
                    flag_lock.release()
                else:
                    flag_lock.acquire()
                    flag = False
                    flag_lock.release()
                time.sleep(1)
            time.sleep(0.1)
'''
连接相机
不断更新全局变量Img
'''
def get_img_from_camera_net(url,level_flag):
    global Img,isCameraLinked
    if level_flag==0:#调试模式
        cap = cv2.VideoCapture(url)  # 调用摄像头‘0’一般是打开电脑自带摄像头，‘1’是打开外部摄像头（只有一个摄像头的情况）
        while False == cap.isOpened():
            print("相机未开启")
            cap = cv2.VideoCapture(url)
            ret, frame = cap.read()
        else:
            print("相机已开启")

        # cap.set(cv2.CAP_PROP_FRAME_WIDTH, 640)  # 设置图像宽度
        # cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 480)  # 设置图像高度
        # cap.set(cv2.CAP_PROP_FPS, 25)  # 设置帧率
        # 显示图像
        while True:
            try:
                start = time.time()
                ret, frame = cap.read()
                if ret is False:
                    print("断开连接，自主重连")
                    cap = cv2.VideoCapture(url)
                    ret, frame = cap.read()
                frame = frame[80:670, 280:1010]
                # cv2.namedWindow("frame", cv2.WINDOW_NORMAL)
                # cv2.imshow("frame", frame)
                time.sleep(0.001)
                # 获取测试图像
                Img = frame
                if isCameraLinked == False:
                    isCameraLinked = True
                end = time.time()
                # print("此张图读取到写入耗时为:",end-start)
            except BaseException as e:
                print(e)
                print("相机重连")
                print("若重连无效，建议重启")
                cap = cv2.VideoCapture(url)
                ret, frame = cap.read()

            if cv2.waitKey(1) & 0xFF == ord('q'):
                break

        cap.release()  # 释放摄像头
        cv2.destroyAllWindows()  # 销毁窗口
    if level_flag==1:#工作模式
        cap = cv2.VideoCapture(url)  # 调用摄像头‘0’一般是打开电脑自带摄像头，‘1’是打开外部摄像头（只有一个摄像头的情况）
        while False == cap.isOpened():
            cap = cv2.VideoCapture(url)
            ret, frame = cap.read()

        # cap.set(cv2.CAP_PROP_FRAME_WIDTH, 3840)  # 设置图像宽度
        # cap.set(cv2.CAP_PROP_FRAME_HEIGHT, 2748)  # 设置图像高度
        # cap.set(cv2.CAP_PROP_FPS, 16)  # 设置帧率
        # 显示图像
        while True:
            try:
                ret, frame = cap.read()
                if ret is False:
                    cap = cv2.VideoCapture(url)
                    ret, frame = cap.read()
                # 获取测试图像
                frame = frame[80:670,280:1010]
                Img = frame
                isCameraLinked  = True
                time.sleep(0.001)

            except BaseException as e:
                cap = cv2.VideoCapture(url)
                ret, frame = cap.read()

def showImg(windowName,img):
    cv2.namedWindow(windowName, cv2.WINDOW_NORMAL)
    cv2.imshow(windowName, img)
    cv2.waitKey(0)

if __name__ == '__main__':
    camera_url = "rtsp://admin:v12345678@192.168.0.80:554/cam/realmonitor?channel=1&subtype=0"
    client_url = "opc.tcp://192.168.0.107:4840/"
    # client_url = "opc.tcp://LAPTOP-91F2HJTJ:53530/OPCUA/SimulationServer"
    userName = "VILAS"
    password = "11111111"
    level_flag =0
    rate = 0.0001

    #设置三把锁对应三个不同全局变量
    count_lock = threading.Lock()
    flag_lock = threading.Lock()
    Img_lock = threading.Lock()

    #创建三个线程
    camera_thread = threading.Thread(target=get_img_from_camera_net,args=(camera_url,level_flag))
    overlapDetection_thread = threading.Thread(target=overlapDetection,args=(rate,level_flag))
    camera_thread.start()
    overlapDetection_thread.start()
    client_thread = threading.Thread(target=establishMyClient,args=(client_url,userName,password))
    client_thread.start()





